<?php

namespace App\Services\Call;

use App\Actions\PaycallAction;
use App\Dao\PayCallDao;
use App\Exception\MessageException;
use App\Model\PayCall;
use App\Model\User;
use App\Utils\MemcacheClient;

class AliveService
{

    /**
     * Note - 接听方每6秒请求一次的接口（在answer成功之后立刻发起）
     * DateTime 2024/8/21 16:22
     * User Admin
     * @param mixed $userInfo
     * @param mixed $params
     */
    public function answerAlive(mixed $userInfo, mixed $params)
    {
        $uid = $userInfo['id'];
        $user_id = intval($params['user_id']); // 发起方
        $call_id = intval($params['call_id']);
        $roger = intval($params['roger']); // 1表示已收到流，0表示还没收到

        if ($userInfo['sex'] == 1) {
            $is_anchor = false;
            $anchorId = $user_id;
            $userId = $uid;
        } else {
            $is_anchor = true;
            $anchorId = $uid;
            $userId = $user_id;
        }

        $paycall = PayCallDao::getInstance()->getCallCache($call_id, true);
        if (empty($paycall)) {
            // Tool::JSON(\CodeData::NEED_TIPS, '', '通话不存在');
            throw new MessageException('通话不存在');
        }

        if ($paycall['anchor_id'] != $anchorId || $paycall['user_id'] != $userId) {
            // Tool::JSON(\CodeData::NEED_TIPS, '', '通话不存在');
            throw new MessageException('通话不存在');
        }
        logInfo("answer_alive", ['call_id' => $call_id, 'line' => 0, 'pay_call' => $paycall]);
        //表明自己接听 在线
        PayCallDao::getInstance()->keepAliveStatus($uid, $call_id);

        $time = time();
        $is_balance = false;
        $result = 0;
        $desc = '持续通话中';

        //用户每次扣费的时间间隔
        $timers = PROFIT_INTERVAL;
        if ($paycall['status'] == 1) {
            // 通话结束
            $is_balance = true;
            if (in_array($paycall['extend'], array(11, 12, 21, 22))) {
                $result = -1;
            } else {
                $result = 1;
            }
            $desc = getReason($paycall['extend']);
            $update_arr = [];
        } else {
            // 收到流 && 不是主播 && 没有首次扣费时间
            if ($roger == 1 && !$is_anchor && $paycall['last_pay_time'] == 0) {
                $firstRet = $this->firstAnser($paycall, $call_id, $time);
                // ['is_balance' => true, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr]
                if ($firstRet) {
                    $is_balance = $firstRet['is_balance'];
                    $result = $firstRet['result'];
                    $desc = $firstRet['desc'];
                    $update_arr = $firstRet['update_arr'];
                }
            } else {
                // 第n次轮询
                $nRet = $this->secondAnser($paycall, $call_id, $user_id, $timers);
                if ($nRet) {
                    $is_balance = $nRet['is_balance'];
                    $result = $nRet['result'];
                    $desc = $nRet['desc'];
                    $update_arr = $nRet['update_arr'];
                }
            }
        }

        MemcacheClient::getInstance()->delete('last_pay_call_item_' . $uid);
        $rs = array('result' => $result);
        $gift_count = '';
        if ($is_anchor) {
            $gift_count = strval(User::query()->where('id', '=', $user_id)->value("gift_count"));
        }
        $rs['gift_count'] = $gift_count;
        if ($is_balance) {
            if (CHARGE_CALL_VERSION) {
                $paycallAction = new PaycallAction();
                //结算
                $balanceData = $paycallAction->settleCall($call_id, $is_anchor, $uid, $update_arr);
            } else {
                $balanceData = [];
            }

            $rs['msg'] = $balanceData;
        }
        logInfo("answer_alive", ['call_id' => $call_id, 'line' => 4, 'res' => $rs]);
        return formatData($rs, 200, 200, $desc);
    }


    /**
     * Note - 通话接通后，第一次轮询
     * DateTime 2024/8/21 16:58
     * User Admin
     * @param $paycall
     * @param $call_id
     * @param $time
     * @return array|bool
     */
    private function firstAnser($paycall, $call_id, $time)
    {
        if (CHARGE_CALL_VERSION) {
            $paycallAction = new PaycallAction();
            // 支付扣费
            $ret = $paycallAction->payForCall($paycall);
        } else {
            $ret = array('code' => 1, 'msg' => '免费通话中');
        }

        logInfo("answer_alive", ['call_id' => $call_id, 'line' => 1, 'res' => $ret]);
        if ($ret['code'] == 1) {
            //成功
            if (isset($ret['type'])) {
                if ($ret['type'] == 1) {
                    // 匹配初始化处理
                    // $payCallModel->updateByWhere(array('start_time' => $time, 'end_time' => $time + 1), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)->where('status', 0)
                        ->update(['start_time' => $time, 'end_time' => $time + 1]);
                } else {
                    // $payCallModel->updateByWhere(array('end_time' => time()), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)->where('status', 0)->update(['end_time' => time()]);
                }
            } else {
                if ($paycall['start_time'] > 0) {
                    // $payCallModel->updateByWhere(array('end_time' => time(), 'last_pay_time' => time()), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)->where('status', 0)->update(['end_time' => time(), 'last_pay_time' => time()]);
                } else {
                    // $payCallModel->updateByWhere(array('start_time' => $time, 'end_time' => $time + 1, 'last_pay_time' => $time), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)->where('status', 0)
                        ->update(['start_time' => $time, 'end_time' => $time + 1, 'last_pay_time' => $time]);
                }
            }
            return false;
        } elseif ($ret['code'] == -1) {
            // 扣费失败
            // $is_balance = true;
            $result = -1;
            $desc = '用户余额不足，通话结束';
            $update_arr = array('status' => 1, 'extend' => '21', 'end_time' => time());
            return ['is_balance' => true, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
        }
    }


    /**
     * Note - 通话接通后，第N次轮询
     * DateTime 2024/8/21 17:06
     * User Admin
     * @param $paycall
     * @param $call_id
     * @param $user_id
     * @param $timers
     * @return array|false
     */
    private function secondAnser($paycall, $call_id, $user_id, $timers)
    {
        if ($paycall['end_time'] == 0) {
            return false;
        }
        $paycallAction = new PaycallAction();

        if (PayCallDao::getInstance()->verifyOtherStatus($user_id, $call_id)) {// 发起方在线
            if (time() - $paycall['last_pay_time'] >= $timers) {// 结算间隔符合条件
                // $rs = $paycallAction->payForCall($paycall);
                if (CHARGE_CALL_VERSION) {
                    $rs = $paycallAction->payForCall($paycall);
                } else {
                    $rs = array('code' => 1, 'msg' => '免费通话中');
                }
                logInfo("answer_alive", ['call_id' => $call_id, 'line' => 2, 'res' => $rs]);
                if ($rs['code'] == 1) {
                    // 扣费成功
                    // $payCallModel->updateByWhere(array('end_time' => time()), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)->where('status', 0)->update(['last_pay_time' => time()]);
                } elseif ($rs['code'] == -1) {
                    //扣费失败，中断此次通话
                    $is_balance = true;
                    $result = -1;
                    $desc = '用户余额不足，通话结束';
                    $update_arr = array('status' => 1, 'extend' => '22', 'end_time' => time());
                    return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                }
            } else {// 小于结算间隔
                // $payCallModel->updateByWhere(array('end_time' => time()), "id = $call_id and status = 0");
                PayCall::query()->where('id', $call_id)->where('status', 0)->update(['last_pay_time' => time()]);
                MemcacheClient::getInstance()->delete('the_pay_call_' . $call_id);
            }
        } else {// 发起方超时了(发起方不在线)
            $is_balance = true;
            $result = 1;
            $desc = '对方网络超时，通话结束';
            if (time() - $paycall['last_pay_time'] >= $timers) { // 结算间隔符合条件
                // $rs = $paycallAction->payForCall($paycall);
                if (CHARGE_CALL_VERSION) {
                    $rs = $paycallAction->payForCall($paycall);
                } else {
                    $rs = array('code' => 1, 'msg' => '免费通话中');
                }
                logInfo("answer_alive", ['call_id' => $call_id, 'line' => 3, 'res' => $rs]);
                if ($rs['code'] == 1) {
                    $update_arr = array('end_time' => time(), 'status' => 1, 'extend' => '23');
                    return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                } elseif ($rs['code'] == -1) {
                    //扣费失败
                    $update_arr = array('status' => 1, 'extend' => '24');
                    return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                }
            } else {// 小于结算间隔
                $update_arr = array('end_time' => time(), 'status' => 1, 'extend' => '25');
                return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
            }
        }
        return false;

    }


    /**
     * Note - 发起方每6秒请求一次的接口（收到第一帧流就请求）
     * DateTime 2024/8/21 18:14
     * User Admin
     * @param mixed $userInfo
     * @param mixed $params
     * @return array
     */
    public function launchAlive(mixed $userInfo, mixed $params)
    {
        $uid = $userInfo['id'];
        $user_id = intval($params['user_id']); //接听方
        $call_id = intval($params['call_id']);
        $roger = intval($params['roger']);

        if ($userInfo['sex'] == 1) {
            $is_anchor = false;
            $anchorId = $user_id;
            $userId = $uid;
        } else {
            $is_anchor = true;
            $anchorId = $uid;
            $userId = $user_id;
        }

        $paycall = PayCallDao::getInstance()->getCallCache($call_id, true);
        if (empty($paycall)) {
            throw new MessageException('通话不存在');
        }

        if ($paycall['anchor_id'] != $anchorId || $paycall['user_id'] != $userId) {
            throw new MessageException('通话不存在');
        }

        logInfo("launch_alive", ['call_id' => $call_id, 'line' => 0, 'pay_call' => $paycall]);
        //表明自己在线
        PayCallDao::getInstance()->keepAliveStatus($uid, $call_id);
        $time = time();
        $is_balance = false;
        $result = 0;
        $desc = '持续通话中';
        $timers = PROFIT_INTERVAL; // 每次扣费时间间隔

        if ($paycall['status'] == 1) {
            $is_balance = true;
            if (in_array($paycall['extend'], array(11, 12, 21, 22))) {
                $result = -1;
            } else {
                $result = 1;
            }
            $desc = getReason($paycall['extend']);
            $update_arr = [];
        } else {
            if ($roger == 1 && !$is_anchor && $paycall['last_pay_time'] == 0) {
                $firstRet = $this->firstLaunch($paycall, $call_id, $time);
                if ($firstRet) {
                    $is_balance = $firstRet['is_balance'];
                    $result = $firstRet['result'];
                    $desc = $firstRet['desc'];
                    $update_arr = $firstRet['update_arr'];
                }
            } else {
                $nRet = $this->secondLaunch($paycall, $call_id, $user_id, $timers);
                if ($nRet) {
                    $is_balance = $nRet['is_balance'];
                    $result = $nRet['result'];
                    $desc = $nRet['desc'];
                    $update_arr = $nRet['update_arr'];
                }
            }
        }
        MemcacheClient::getInstance()->delete('last_pay_call_item_' . $uid);

        $rs = array('result' => $result);

        $gift_count = '';
        if ($is_anchor) {
            $gift_count = strval(User::query()->where('id', $userId)->value("gift_count"));
        }
        $rs['gift_count'] = $gift_count;
        if ($is_balance) {
            if (CHARGE_CALL_VERSION) {
                $paycallAction = new PaycallAction();
                // 结算
                $balanceData = $paycallAction->settleCall($call_id, $is_anchor, $uid, $update_arr);
            } else {
                $balanceData = [];
            }
            $rs['msg'] = $balanceData;
        }

        logInfo("launch_alive", ['call_id' => $call_id, 'line' => 4, 'res' => $rs,]);
        // Tool::JSON(\CodeData::SUCCESS, $rs, $desc);
        return formatData($rs, 200, 200, $desc);
    }


    /**
     * Note - 通话接通后，第一次轮询
     * DateTime 2024/8/21 16:58
     * User Admin
     * @param $paycall
     * @param $call_id
     * @param $time
     * @return array|bool
     */
    private function firstLaunch($paycall, $call_id, $time)
    {
        if (CHARGE_CALL_VERSION) {
            $paycallAction = new PaycallAction();
            //用户收到流之后的第一次请求，初始化开始时间，并扣费
            $ret = $paycallAction->payForCall($paycall);
        } else {
            $ret = array('code' => 1, 'msg' => '免费通话中');
        }
        logInfo("launch_alive", ['call_id' => $call_id, 'line' => 1, 'res' => $ret]);
        if ($ret['code'] == 1) {
            //成功
            if ((isset($ret['type']) && $ret['type'] == 1) || !isset($ret['type'])) {
                // $payCallModel->updateByWhere(array('start_time' => $time, 'end_time' => $time + 1), "id = $call_id and status = 0");
                PayCall::query()->where('id', $call_id)
                    ->where('status', 0)
                    ->update(['start_time' => $time, 'end_time' => $time + 1]);
            }
            return false;
        } else {
            //更新失败
            $is_balance = true;
            $result = -1;
            $desc = '用户余额不足，通话结束';
            $update_arr = array('status' => 1, 'extend' => '21', 'end_time' => time());
            return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
        }

    }


    /**
     * Note - 通话接通后，第N次轮询
     * DateTime 2024/8/21 18:33
     * User Admin
     * @param $paycall
     * @param $call_id
     * @param $user_id
     * @param $timers
     * @return array|false
     */
    private function secondLaunch($paycall, $call_id, $user_id, $timers)
    {
        if ($paycall['end_time'] == 0) {
            return false;
        }
        $paycallAction = new PaycallAction();
        if (PayCallDao::getInstance()->verifyOtherStatus($user_id, $call_id)) {// 接听方在线
            // 判断要不要扣费，结算间隔符合条件
            if (time() - $paycall['last_pay_time'] >= $timers) {
                if (CHARGE_CALL_VERSION) {
                    $rs = $paycallAction->payForCall($paycall);
                } else {
                    $rs = array('code' => 1, 'msg' => '免费通话中');
                }
                logInfo("launch_alive", ['call_id' => $call_id, 'line' => 2, 'res' => $rs]);
                if ($rs['code'] == 1) {
                    // $payCallModel->updateByWhere(array('end_time' => time()), "id = $call_id and status = 0");
                    PayCall::query()->where('id', $call_id)
                        ->where('status', 0)
                        ->update(['end_time' => time()]);
                    return false;
                } elseif ($rs['code'] == -1) {
                    //扣费失败，中断此次通话
                    $is_balance = true;
                    $result = -1;
                    $desc = '用户余额不足，通话结束';
                    $update_arr = array('status' => 1, 'extend' => '12', 'end_time' => time());
                    return ['is_balance' => true, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                }
            } else {
                // $payCallModel->updateByWhere(array('end_time' => time()), "id = $call_id and status = 0");
                PayCall::query()->where('id', $call_id)->where('status', 0)->update(['end_time' => time()]);
                MemcacheClient::getInstance()->delete('the_pay_call_' . $call_id);
            }
        } else {
            //接听方超时了
            $is_balance = true;
            $result = 1;
            $desc = '对方网络超时，通话结束';
            if (time() - $paycall['last_pay_time'] >= $timers) {
                if (CHARGE_CALL_VERSION) {
                    $rs = $paycallAction->payForCall($paycall);
                } else {
                    $rs = array('code' => 1, 'msg' => '免费通话中');
                }
                logInfo("launch_alive", ['call_id' => $call_id, 'line' => 3, 'res' => $rs]);
                if ($rs['code'] == 1) {
                    $update_arr = array('end_time' => time(), 'status' => 1, 'extend' => '13');
                    return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                } elseif ($rs['code'] == -1) {
                    //扣费失败
                    $update_arr = array('status' => 1, 'extend' => '14');
                    return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
                }
            } else {
                $update_arr = array('end_time' => time(), 'status' => 1, 'extend' => '15');
                return ['is_balance' => $is_balance, 'result' => $result, 'desc' => $desc, 'update_arr' => $update_arr];
            }
        }
        return false;
    }


}